#######################################################################################
#                                                                                     #
#      Copyright 2007 Raja <rajajs@gmail.com>                                         #
#                                                                                     #
#      This program is free software; you can redistribute it and/or modify           #
#      it under the terms of the GNU General Public License as published by           #
#      the Free Software Foundation; either version 2 of the License, or              #
#      (at your option) any later version.                                            #
#                                                                                     #
#      This program is distributed in the hope that it will be useful,                #
#      but WITHOUT ANY WARRANTY; without even the implied warranty of                 #
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                  #
#      GNU General Public License for more details.                                   #
#                                                                                     #
#      You should have received a copy of the GNU General Public License              #
#      along with this program; if not, write to the Free Software                    #
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # 
#                                                                                     #
#######################################################################################
"""
Get the agenda from a users google calendar and format it for display in dzen or conky
"""

### Imports ###
import gdata.calendar.service
import atom
import datetime
from optparse import OptionParser

#############################################################
## variables for users to edit ##
#################################
gcal_address  = ''          # The private address for your calendar
username      = ''          # username for google services 
maxEvents     = 5           # maximum events to show per day
daysToShow    = 4           # Number of days from today to include in agenda
dateformat    = "%d-%m-%Y"  # Format in which date is to be shown
datecolor = 'blue'
timecolor = 'grey'
eventcolor = 'white'
#############################################################

#username should have '@gmail.com' in the end
if username[-10:] <> '@gmail.com':
    username += '@gmail.com'

# Get magic cookie from the private calendar url
magic_cookie = gcal_address.split('/')[6] #simpler than using re

one_day = datetime.timedelta(days=1)

################################################################


def getFeed(some_day):
    """
    Query the calendar service and get the agenda
    for some day.
    some_day is a datetime.date object
    """
    query = gdata.calendar.service.CalendarEventQuery(username, magic_cookie, 'full')

    # set query time limits from some_day to the next day
    query.start_min = some_day.isoformat()
    query.start_max = (some_day + one_day).isoformat()

    calendar_service = gdata.calendar.service.CalendarService()
    feed = calendar_service.CalendarQuery(query)
    
    return feed
    

def parseFeed(feed):
    """
    Parse the feed to get the events
    and details of each event
    """ 
    events = []
    
    for event in feed.entry:
        for repeat in event.when:
            this_event = dict()
            this_event["title"] = event.title.text
            this_event["start"] = repeat.start_time
            this_event["end"] = repeat.end_time
            this_event["notify"] = event.send_event_notifications
        
            events.append(this_event)
        
    return events
    
    
def format24to12(time_24h):
    """
    convert time in a 24 h format (like 17:15)
    to a 12 h format (like 5.15 pm)
    """
    sep = '.'
    suffix = "am"
    
    hr, min = time_24h.split(':')
    
    if int(hr) > 12:
        suffix = "pm"
        
    if int(hr) > 13:
        hr = str(int(hr)-12)
        
    # for aligning times of events, add space if its a single digit hour
    if len(hr) == 1:
        hr = ' ' + hr
        
    return ''.join([hr, sep, min, suffix])
    
    
def formatTime(events):
    """
    Format the times in the list of
    events and then sort events by start time
    """
    for event in events:
                
        if len(event["start"]) == 10:
            event["time"] = "Full day       "
            event["timeindex"]  = 0
        
        else:
            start_time = format24to12(event["start"][11:16])
            end_time = format24to12(event["end"][11:16])
            event["time"] = "-".join([start_time,end_time])
            #create an index to allow sorting by start time
            event["timeindex"] = float(event["start"][11:16].replace(':','.'))
    
    #sort events by start time
    events.sort(lambda x, y: int(x["timeindex"]-y["timeindex"]))
    
    return events


def printDayEvents(datestring,events):
    """
    print date followed by the 
    title and time for each event
    """
    if datestring <> '':
        print datestring
    
    for i in range(min(len(events),maxEvents)):
        event = events[i]
        print "^fg(%s) %s  %s" %(eventcolor,event["time"],event["title"])
    
    print ""
        
def genDzenOutput():
    """
    For dzen, print events for specified number of days 
    with max events per day as specified.
    Output is formatted for dzen with (x+1)*y lines in the 
    slave window, where x is the number of events per day
    and y is the number of days    
    """
    
    day = datetime.date.today()
    
    print "^tw() ^fg(%s) %s" %(datecolor, day.strftime(dateformat))
    print "^cs()"
    
    for days in range(daysToShow):
        feed = getFeed(day)    
        events = formatTime(parseFeed(feed))
        
        #print date and events
        print "^fg(%s) %s" %( datecolor, day.strftime(dateformat))
        
        for i in range(min(len(events),maxEvents)):
            event = events[i]
            print "^r(5x5) ^fg(%s) %s ^fg(%s) %s" %(timecolor,event["time"],eventcolor,event["title"])
        print ''
                
        day += datetime.timedelta(days=1)
    

def genConkyOutput():
    """
    Print the days events for conky
    """
       
    day = datetime.date.today()
    feed = getFeed(day)
    events = formatTime(parseFeed(feed))
    
    for i in range(min(len(events),maxEvents)):
        event = events[i]
        print " %s  %s" %(event["time"],event["title"])
    print ''
        
###############################

parser = OptionParser()
parser.add_option("-c", "--conky", action='store_true',dest="format_for_conky",
                  help="Format output for conky")
parser.add_option("-d", "--dzen", action='store_false',dest="format_for_conky",
                  help="Format output for dzen")
(options, args) = parser.parse_args()


if options.format_for_conky:                  
    genConkyOutput()
else:
    genDzenOutput()
